package org.jeecg.modules.payment.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import org.jeecg.modules.payment.PaymentBase;
import org.jeecg.modules.payment.dto.PaymentRequest;
import org.jeecg.modules.payment.vo.PaymentResponse;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 功能描述
 *
 * @author: wei
 * @date: 2024年08月06日 17:01
 */
@Service
public class PaymentBmwlImpl implements PaymentBase {

    String URL = "https://pay.bmwl.asia/mapi.php";
    String PDI = "1014";
    String SECRET_KEY = "xOOfjZoQ1zpX9qB9FzfpuLlzU9SOxdqp";

    @Override
    public PaymentResponse createOrder(PaymentRequest paymentRequest) {
        paymentRequest.setPid(PDI);
        paymentRequest.setSignType("MD5");

        Map<String, Object> params = new HashMap<>();
        params.put("pid", paymentRequest.getPid());
        params.put("type", paymentRequest.getType());
        params.put("out_trade_no", paymentRequest.getOutTradeNo());
        params.put("notify_url", paymentRequest.getNotifyUrl());
        params.put("name", paymentRequest.getName());
        params.put("money", String.valueOf(paymentRequest.getMoney()));
        params.put("clientip", paymentRequest.getClientIp());
        params.put("device", paymentRequest.getDevice());

        String sign = generateSignature(params);
        paymentRequest.setSign(sign);
        params.put("sign", paymentRequest.getSign()); // 假设这是之前生成的签名，现在重新生成时不包括它
        params.put("sign_type", paymentRequest.getSignType());

        // 发起支付请求
        String response = HttpUtil.post(URL, params);
        PaymentResponse bmwResponse = JSONUtil.toBean(response, PaymentResponse.class);
        return bmwResponse;
    }

    /**
     * 生成签名
     *
     * @param params 参数Map
     * @return 签名字符串
     */
    public String generateSignature(Map<String, Object> params) {
        // 第一步：筛选出非空且不是sign, sign_type的参数
        Map<String, String> filteredParams = new HashMap<>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue().toString();
            if (value != null && !value.isEmpty() && !"sign".equals(key) && !"sign_type".equals(key)) {
                filteredParams.put(key, value);
            }
        }

        // 第二步：按照参数名ASCII码从小到大排序
        List<String> keys = new ArrayList<>(filteredParams.keySet());
        Collections.sort(keys);

        // 第三步：拼接成URL键值对格式
        StringBuilder queryString = new StringBuilder();
        for (String key : keys) {
            queryString.append(key).append("=").append(filteredParams.get(key)).append("&");
        }

        // 移除最后一个多余的"&"
        if (queryString.length() > 0) {
            queryString.setLength(queryString.length() - 1);
        }

        // 第四步：将拼接好的字符串与商户密钥KEY进行MD5加密
        return md5(queryString.toString() + SECRET_KEY);
    }

    /**
     * 对字符串进行MD5加密
     *
     * @param input 输入字符串
     * @return MD5加密后的字符串
     */
    private String md5(String input) {
        try {
            // 创建一个MD5 MessageDigest 实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 使用指定的字节数组更新摘要
            md.update(input.getBytes());
            // 完成哈希计算，得到结果
            byte[] digest = md.digest();
            // 将得到的字节转换成十六进制表示的字符串形式
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}
